
<template>
  <div class="person">
    <h2>情况一、监视【ref】定义的【基本类型】数据</h2>
    <h3>当前求和为：{{ sum }}</h3><br>
    <button @click="changeSum">点我sum+1</button><br>
    <hr>
     <h2>情况二、监视【ref】定义的【对象类型】数据</h2>
    <h3>姓名：{{ YeNan.name }}</h3>
    <h3>年龄：{{ YeNan.age }}</h3>
    <button @click="changeName">修改名字</button>
    <button @click="changeAge">修改年龄</button>
    <button @click="changePerson">更换人员</button><br>
    <hr>
     <h2>情况三、监视【reactive】定义的【对象类型】数据</h2>
    <h3>姓名：{{ halfSugar.name }}</h3>
    <h3>年龄：{{ halfSugar.age }}</h3>
    <button @click="changeHalfSugarName">修改名字</button>
    <button @click="changeHalfSugarAge">修改年龄</button>
    <button @click="changeHalfSugar">更换人员</button><br>
    <h3>测试obj：{{ obj.a.b.c }}</h3>
    <button @click="handleObj">点我修改obj</button><br>
    <hr>
    <h2>情况四、监视ref或reactive定义的【对象类型】数据中的某个属性</h2>
    <h3>姓名： {{ Ximy.name }}</h3>
    <h3>年龄： {{ Ximy.age }}</h3>
    <h3>汽车： {{ Ximy.car.c1 }} 、 {{ Ximy.car.c2 }}</h3>
    <button @click="changeXimyName">修改名字</button>
    <button @click="changeXimyAge">修改年龄</button>
    <button @click="changeXimyC1">修改第一台车</button>
    <button @click="changeXimyC2">修改第二台车</button>
    <button @click="changeXimyAll">修改所有车</button>
    <hr>
    <h2>情况五、监视上述多个数据</h2>
    <h3>姓名： {{ Yexue.name }}</h3>
    <h3>年龄： {{ Yexue.age }}</h3>
    <h3>汽车： {{ Yexue.car.c1 }} 、 {{ Yexue.car.c2 }}</h3>
    <button @click="changeYexueName">修改名字</button>
    <button @click="changeYexueAge">修改年龄</button>
    <button @click="changeYexueC1">修改第一台车</button>
    <button @click="changeYexueC2">修改第二台车</button>
    <button @click="changeYexueAll">修改所有车</button>
    <hr>
  </div>
</template>
<script lang="ts" setup>
import { ref,reactive,computed, watch } from 'vue';
// Watch 
//   作用：监视数据的变化(和Vue2中的watch作用一致)
//   特点: Vue3中watch中能监视以下四种数据:
//           1、ref定义的数据
//           2、reactive定义的数据
//           3、函数返回一个值
//           4、一个包含上述内容的数组

//一、情况一
// 监视【ref】定义的【基本类型】数据 ：直接写数据名即可，监视的是其value值的改变
   let sum = ref(0)
   function changeSum(){
    sum.value += 1
   }
   
  // 公式： watch(变量，callback,config)
  const sumStop =   watch(sum,(newVal,oldVal)=>{
    // 这里直接写sum即可，不用写sum.value
    console.log('【ref】定义的【基本类型】数据',newVal,oldVal);
    // 解除监视
    if (newVal >= 10) {
      sumStop() //解除监视 直接调watch返回的回调函数即可
    }
   },{})
  //  watch函数是有返回值的,返回值是一个回调函数
  console.log('看看watch的返回值',sumStop);

//二、情况二
  // 监视【ref】定义的【对象类型】数据：直接写数据名，监视的是对象的【地址值】，弱项监视对象内部的数据，要手动开启深度监听。
  let YeNan = ref({
    name:'夜南漫剪',
    age:18
  })
  function changeName(){
    YeNan.value.name += '~'
    // 这里只是更改了对象的name的属性值，所以watch里的oldVal和newVal值是一样的
  }
  function changeAge(){
    YeNan.value.age += 1
    // 这里只是更改了对象的age的属性值，所以watch里的oldVal和newVal值是一样的
  }
  function changePerson(){
    YeNan.value = {
      name:'Dear丶夜雪',
      age:769
    }
    // 这里更改了对象的地址值，所以watch里的oldVal和newVal值不一样的
  }
  watch(YeNan,(newVal,oldVal)=>{
    console.log('【ref】定义的【对象类型】数据',newVal,oldVal);
  },{deep:true})
  // 注意： 若修改的是ref定义的对象中的属性，newVal和oldVal都是新值，因为它们是同一个对象
  //        若修改整个ref定义的对象，newVal是新值,oldVal是旧值，因为不是同一个对象了

//三、情况三 
  //  监视【reactive】定义的【对象类型】数据，且默认开起来深度监视(无法手动关闭，2025/06/17 可以手动关闭了)
  let halfSugar = reactive({
    name:'半糖美式',
    age:35
  })
  function changeHalfSugarName(){
    halfSugar.name += '~'
  }
  function changeHalfSugarAge(){
    halfSugar.age += 1
  }
  function changeHalfSugar(){
    Object.assign(halfSugar,{
      name:'奇迹行者',
      age:80
    })
  }
  watch(halfSugar,(newVal,oldVal)=>{
    console.log('【reactive】定义的【对象类型】数据',newVal,oldVal);
    
  })

  let obj = reactive({
    a:{
      b:{
        c:666
      }
    }
  })
  function handleObj(){
    obj.a.b.c = 999
  }
  // 隐式创建深度监听模式，且无法手动关闭 （2025/06/17 可以手动关闭了）
  watch(obj,(newVal,oldVal)=>{
    console.log('测试obj',newVal,oldVal);
  },{deep:false})  //deep:false 不生效  2025/06/17 生效了

// 四、情况四
// 监视ref或reactive定义的【对象类型】数据中的某个属性，注意点如下：
      //1、若该属性值不是【对象类型】，需要写成函数形式
      //2、若该属性值是依然是【对象类型】，可直接编，也可写成函数，不过建议写成函数 
    let Ximy = reactive({
      name:'血刃酒馆夜南',
      age:18,
      car:{
        c1:'青桔',
        c2:'爱玛'
      }
    })
    function changeXimyName(){
      Ximy.name += '-TnT'
    }
    function changeXimyAge(){
      Ximy.age += 1
    }
    function changeXimyC1(){
      Ximy.car.c1 = '哈罗单车'
    }
    function changeXimyC2(){
      Ximy.car.c2 = '兰博基尼'
    }
    function changeXimyAll(){
      Ximy.car = {
        // 这样直接更改不会报错,因为更改的是Ximy的car属性，Ximy的地址值未改变
        c1:'宝马',
        c2:'大众'
      }
    }
    // 监视的属性值不是对象类型
    watch(()=>Ximy.name,(newVal,oldVal)=>{
      console.log('情况四，1、监视对象的属性值不是对象类型的数据',newVal,oldVal);
    })
    // 监视的属性值是对象类型
        // 1、直接写属性
    // watch(Ximy.car,(newVal,oldVal)=>{
    // // 这种情况，当更改c1和c2属性值时，监视会触发，但是当更改car的属性值监视是不会触发
    //   console.log('情况四，2、监视对象的属性值是对象类型的数据',newVal,oldVal);
    // })
    // 2、写函数
    // watch(()=>Ximy.car,(newVal,oldVal)=>{
    // // 这种情况，当更改c1和c2属性值时，监视不会触发，但是当更改car的属性值是会触发的
    //   console.log('情况四，2、监视对象的属性值是对象类型的数据',newVal,oldVal);
    // })
    // 3、解决办法，想要让c1、C2和car无论哪个属性值发生改变时都触发监听，写函数式并打开深度监听
    watch(()=>Ximy.car,(newVal,oldVal)=>{
    // 这种情况，当更改c1和c2属性值时，监视不会触发，但是当更改car的属性值是会触发的
      console.log('情况四，2、监视对象的属性值是对象类型的数据',newVal,oldVal);
    },{deep:true})

      // 结论：监视的要是对象里的属性，那么最好写函数式
      // 注意点：若是对象监视的只是地址值可以不需要开启深度监视;需要关注对象内部，需要手动开启深度监视

// 五、情况五
    // 监视上述多个数据，比如 要求监视人的名字和第一台车两个属性
    let Yexue = reactive({
      name:'Dear丶夜雪',
      age:25,
      car:{
        c1:'灭龙剑巴鲁姆克',
        c2:'漫游枪手的威权'
      }
    })
    function changeYexueName(){
      Yexue.name += '-TnT'
    }
    function changeYexueAge(){
      Yexue.age += 1
    }
    function changeYexueC1(){
      Yexue.car.c1 = '太极天帝剑'
    }
    function changeYexueC2(){
      Yexue.car.c2 = '世界树的精灵'
    }
    function changeYexueAll(){
      Yexue.car = {
        c1:'梁月的钝剑:神',
        c2:'武神凌云剑'
      }
    }
    // 公式：watch([属性1，属性2,...,属性3]，()=>{})
    // 将要监视的属性放到集中放到数组中区，数组中的属性写法需要遵守上述几种情况的规则
    watch([()=>Yexue.name,Yexue.car],(newVal,oldVal)=>{
      console.log("情况五,监视上述多个数据",newVal,oldVal);
    })
</script>
<style>
button{
  margin-left: 10px;
}
</style>